#include<stdlib.h>
#include<stdbool.h>
#include<stdio.h>
#define unlikely(x) __builtin_expect(!!(x), 0)

#define LOG_ERR(fmt,...) printf("err:"fmt,##__VA_ARGS__)
#define LOG_INFO(fmt,...) printf("info:"fmt,##__VA_ARGS__)

#define MAX_SIZE 100
static int data_counter = 0;
/**
 * pdata 是guest_dev slots存放的数据
 * 
 * int armed:表示数据是否可用
 * int data:暂时表示数据
 */
struct pdata{
    int armed;
    int data;
};
/**
 * slot用来表示一个数组，它包含数组的起始地址和数组的元素数量
 */
struct slot{
    struct pdata *slots;
    int slots_num;
};
/**
 * 栈
 */
struct free_stack{
    int data[MAX_SIZE];
    int top;
};

/**
 * guest_dev 结构体表示中间整个大的结构，包括一个free_stack和一个数组结构
 */
struct guest_dev{
    struct slot *g_slots;
    struct free_stack *g_free_stack;
};

void initStack(struct free_stack *s){
    s->top = -1;
}
bool isEmpty(struct free_stack *s){
    return s->top==-1;
}
bool isFull(struct free_stack *s){
    return s->top == MAX_SIZE-1;
}
bool push(struct free_stack *s,int value){
    if(isFull(s)){
        LOG_ERR("stack is full,can't push");
        return false;
    }
    s->data[++(s->top)] = value;
    LOG_INFO("%d被压入栈,当前top在:%d\n",value,s->top);
    return true;
}
bool pop(struct free_stack *s,int *value){
    if(isEmpty(s)){
        LOG_ERR("stack is empty,can't pop\n");
        return false;
    }
    *value = s->data[(s->top)--];
    LOG_INFO("%d出栈\n",*value);
    return true;
}
void show_stack(struct free_stack *s){
    if(isEmpty(s)){
        LOG_INFO("当前栈为空\n");
        return;
    }
    for(int i=0;i<=s->top;i++){
        printf("stack element[%d]:%d\n",i,s->data[i]);
    }
    printf("\n");
}

/**
 * 
 * return 0:success
 * return -1:failed
 */
int init_free_stack(struct guest_dev *g_dev){
    g_dev->g_free_stack = (struct free_stack*)calloc(1,sizeof(struct free_stack));
    if(!g_dev->g_free_stack)return -1;
    initStack(g_dev->g_free_stack);
    for(int i=0;i<g_dev->g_slots->slots_num;i++){
        push(g_dev->g_free_stack,i);
    }
    return 0;
}
/**
 * init slots
 * 
 */
int init_slots(struct guest_dev *g_dev,int slots_num){
    if(unlikely(!g_dev)){
        LOG_ERR("g_dev allocate failed!\n");     
        return -1;
    }
    g_dev->g_slots = (struct slot*)calloc(1,sizeof(struct slot));
    if(unlikely(!g_dev->g_slots)){
        LOG_ERR("g_dev->g_slots allocate failed!\n");
        return -1;
    }
    g_dev->g_slots->slots_num = slots_num;
    LOG_INFO("slots_num:%d 初始化完毕\n",g_dev->g_slots->slots_num);
    g_dev->g_slots->slots = (struct pdata*)calloc(slots_num,sizeof(struct pdata));
    if(unlikely(!g_dev->g_slots->slots)){
        LOG_ERR("g_dev->g_slots allocate failed!\n");
        return -1;
    }
    return 0;
}
/**
 * init all need struct
 * 
 * return 0:success
 * return -1:allocate failed
 */
int init(struct guest_dev *g_dev,int slots_num){
    int ret;
    ret = init_slots(g_dev,slots_num);
    if(ret<0){
        LOG_ERR("slots init failed!\n");
        return -1;
    }
    LOG_INFO("init slots success\n");
    ret = init_free_stack(g_dev);
    if(ret<0){
        LOG_ERR("free_stack init failed!\n");
        return -1;
    }
    LOG_INFO("init free_stack success\n");
    return 0;
}
/**
 * this function simulate user consume the guest_dev
 * 
 * 
 */
void user_consume(struct guest_dev *g_dev,int *c_idx){
    // user will find one data that can use
    struct slot *slots = g_dev->g_slots;
    if(!slots){
        LOG_ERR("guest_dev的数组初始化错误\n");
        return;
    }
    struct free_stack *f_stack = g_dev->g_free_stack;
    if(!f_stack){
        LOG_ERR("guest_dev的free_stack初始化错误\n");
        return;
    }
    int slots_num = g_dev->g_slots->slots_num;
    for(int i=0;i<slots_num;i++){
        if(slots->slots[i].armed==1){
            *c_idx = i;
            LOG_INFO("用户消费到slots中的slots[%d]数据为:%d,正在消费中...\n",i,slots->slots[i].data);
            return;
        }
    }
    LOG_INFO("当前没有可消费的数据\n");
}
/**
 * this function simulate productor produce data
 */
void product(struct guest_dev *g_dev){
    // user will find one data that can use
    struct slot *slots = g_dev->g_slots;
    if(!slots){
        LOG_ERR("guest_dev的数组初始化错误\n");
        return;
    }
    struct free_stack *f_stack = g_dev->g_free_stack;
    if(!f_stack){
        LOG_ERR("guest_dev的free_stack初始化错误\n");
        return;
    }
    // 先从free_stack里面弹出一个
    int free_idx = -1;
    pop(f_stack,&free_idx);
    if(free_idx == -1){
        LOG_ERR("无可用空间，等待用户消费完毕\n");
        return;
    }
    if(free_idx<0||free_idx>=slots->slots_num){
        LOG_ERR("弹出的free_idx超出适用范围请仔细检查!!!\n");
    }
    slots->slots[free_idx].data = data_counter++;
    slots->slots[free_idx].armed = 1;
    LOG_INFO("生产者生产了一次数据:%d,存放到了slots[%d]\n",slots->slots[free_idx].data,free_idx);
}
void consume_done(struct guest_dev *g_dev,int idx){
    g_dev->g_slots->slots[idx].armed = 0;
    push(g_dev->g_free_stack,idx);
    LOG_INFO("%d消费完毕，将其加入free_stack\n",idx);
}


void cleanup_guest_dev(struct guest_dev *g_dev) {
    if (!g_dev) return;
    if (g_dev->g_slots && g_dev->g_slots->slots) {
        free(g_dev->g_slots->slots);
        g_dev->g_slots->slots = NULL;
    }
    if (g_dev->g_slots) {
        free(g_dev->g_slots);
        g_dev->g_slots = NULL;
    }
    if (g_dev->g_free_stack) {
        free(g_dev->g_free_stack);
        g_dev->g_free_stack = NULL;
    }
}
int main(){
    struct guest_dev *my_guest_dev = calloc(1, sizeof(struct guest_dev));
    // 初始化实验模块
    init(my_guest_dev,4);
    // 开始模拟
    show_stack(my_guest_dev->g_free_stack);
    product(my_guest_dev);
    show_stack(my_guest_dev->g_free_stack);
    int c_idx = -1;
    user_consume(my_guest_dev,&c_idx);
    if(c_idx==-1)LOG_INFO("没消费到\n");
    else consume_done(my_guest_dev,c_idx);
    show_stack(my_guest_dev->g_free_stack);
    // 释放资源
    cleanup_guest_dev(my_guest_dev);
    free(my_guest_dev);
    my_guest_dev=NULL;
    LOG_INFO("资源释放完毕\n");
}